package com.codeyang.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.codeyang.constant.MenuConstant;
import com.codeyang.domain.SysMenu;
import com.codeyang.mapper.SysMenuMapper;
import com.codeyang.service.SysMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 描述: TO-删除标志-DO
 *
 * @author CodeYang_Site
 * @version 2021/5/24 10:03
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    private StringRedisTemplate redisTemplate;


    @Autowired
    private SysMenuMapper sysMenuMapper;

    /**
     * 根据用户的id查询菜单并且组装
     * 1.先查缓存 yes return
     * 2.no 查出来 存进去 return
     *
     * @param userId 用户id
     * @return
     */
    @Override
    public List<SysMenu> findMenuById(String userId) {
        List<SysMenu> sysMenuList = null;
        //1 从redis中查询
        String menuStr = redisTemplate.opsForValue().get(MenuConstant.MENU_PREFIX + userId);
        if (StringUtils.hasText(menuStr)) {
            //redis不为null 缓存有直接干,redis里只直接存 List 不存树型增加效率
            sysMenuList = JSON.parseArray(menuStr, SysMenu.class);
        } else {
            //缓存没有,查询DB
            sysMenuList = sysMenuMapper.findMenuListById(Long.valueOf(userId));

            if (CollectionUtils.isEmpty(sysMenuList)) {
                //如果DB也没有直接返回
                return null;
            }
            //这里DB肯定有了,存入redis,设置过期时间7天
            redisTemplate.opsForValue().set(MenuConstant.MENU_PREFIX + userId, JSON.toJSONString(sysMenuList), Duration.ofDays(7));
        }

        //到这里肯定是有数据了 但是要把数据转成树 for|递归
        return translateTree(sysMenuList, 0L);
    }


    /**
     * 转换菜单树
     *
     * @param sysMenuList 菜单数据
     * @param pid         父节点ID
     * @return
     */
    private List<SysMenu> translateTree(List<SysMenu> sysMenuList, long pid) {
        //1.先拿到根节点
        // desc: 拿到 pid节点下面所有 父节点id为pid的节点数据 --过滤
        // 相当于拿到根节点菜单数据 可能有 add菜单 del菜单 都是 0
        List<SysMenu> rootList = sysMenuList.stream()
                .filter(sysMenu -> sysMenu.getParentId().equals(pid))
                .collect(Collectors.toList());
        //2.循环
        rootList.forEach(root -> {
            // 菜单菜单树中 菜单的父id为 rootList中的 menuId的集合
            List<SysMenu> childList = sysMenuList.stream()
                    .filter(sysMenu -> sysMenu.getParentId().equals(root.getMenuId()))
                    .collect(Collectors.toList());
            //2.将childList设置到rootList中去
            root.setList(childList);
        });
        return rootList;
    }
}
